package weeny.pre.control;

import java.awt.geom.Rectangle2D;
import java.util.Iterator;

import prefuse.Constants;
import prefuse.Visualization;
import prefuse.action.layout.AxisLayout;
import prefuse.action.layout.Layout;
import prefuse.data.Table;
import prefuse.data.Tuple;
import prefuse.data.tuple.TupleSet;
import prefuse.visual.VisualItem;

public class ParallelCoordinateLayout extends Layout{

	private String polyField = null;
	private String[] columns = null;
	private AxisLayout axisLayout = null;
	public ParallelCoordinateLayout(String group, String field, String[] columns) {
		super(group);
		polyField = field;
		this.columns = columns;
		this.axisLayout = new AxisLayout(group, "");
		this.axisLayout.setVisualization(m_vis);
		this.axisLayout.setAxis(Constants.Y_AXIS);
	}
	@Override
	public void setLayoutBounds(Rectangle2D b) {
		this.axisLayout.setLayoutBounds(b);
		super.setLayoutBounds(b);
	}
	@Override
	public void setVisualization(Visualization vis) {
		super.setVisualization(vis);
		this.axisLayout.setVisualization(vis);
	}
	@Override
	public void run(double frac) {
		preparePolyField();
		for (int i = 0; i< columns.length; i++){
			axisLayout.setDataField(columns[i]);
			axisLayout.setDataType(getDataType(m_vis.getGroup(m_group), columns[i]));
			axisLayout.run(0);
			biasValue(i);
		}
		TupleSet ts = m_vis.getGroup(m_group);
		for (Iterator<Tuple> it = ts.tuples(); it.hasNext(); ){
			Tuple t = it.next();
			t.setDouble(VisualItem.X, 0);
			t.setDouble(VisualItem.Y, 0);
		}
	}
	private void biasValue(int index){
		TupleSet ts = m_vis.getGroup(m_group);
		for (Iterator<Tuple> it = ts.tuples(); it.hasNext(); ){
			Tuple t = it.next();
			float[] poly = (float[]) t.get(polyField);
			poly[index*2+1] = (float) t.getDouble(VisualItem.Y);
		}
	}
	protected void preparePolyField(){
		Rectangle2D b = getLayoutBounds();
		float min = (float) b.getMinX();
		float inc = (float) (b.getMaxX()-b.getMinX());
		inc /= (columns.length-1);
		TupleSet ts = m_vis.getGroup(m_group);
		for (Iterator<Tuple> it = ts.tuples(); it.hasNext(); ){
			Tuple t = it.next();
			float[] poly = (float[]) t.get(polyField);
			if (poly == null || poly.length != columns.length*2) {
				poly = new float[columns.length*2];
			}
			for(int i = 0; i<columns.length; i++){
				poly[i*2] = i*inc+min;
			}
			t.set(polyField, poly);
		}
	}
    protected int getDataType(TupleSet ts, String field) {
    	boolean numbers = true;
    	if ( ts instanceof Table ) {
    		numbers = ((Table)ts).canGetDouble(field);
    	} else {
    		for ( Iterator it = ts.tuples(); it.hasNext(); ) {
    			if ( !((Tuple)it.next()).canGetDouble(field) ) {
    				numbers = false;
    				break;
    			}
    		}
    	}
    	if ( numbers ) {
    		return Constants.NUMERICAL;
    	} else {
    		return Constants.ORDINAL;
    	}
    }
}
